/**
 * 
 */
package fr.ece.ing4.chatapplication.server;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import org.jgroups.Address;
import org.jgroups.Message;
import org.jgroups.View;

import fr.ece.ing4.chatapplication.api.ChatMessage;
import fr.ece.ing4.chatapplication.api.TransportDriver;
import fr.ece.ing4.chatapplication.api.TransportReceiver;

/**
 * @author enzo
 *
 */
public class ServerController implements TransportReceiver, Observer{

    private final String controlCluster = "ControlCluster";
	private TransportDriver driver;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;
	private int nbClient;
	private static int nb = 0;
	private Address address;
	private List<ChatRoomController> chatRooms;

    public ServerController()
	{
		name = "Server" + nb;
		nbClient = 0;
		driver = new TransportDriver(controlCluster, name, this);
		address = driver.getAddress();
		nb++;
		chatRooms = new ArrayList<ChatRoomController>();

        new ServerFrame(this);
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			new ServerController();
	}

	@Override
	public void printView(View v) {
		// TODO Auto-generated method stub
		System.out.println(" view" + v.toString());
		

	}
	@Override
	public void receiveChatMessage(Message msg) {
		// TODO Auto-generated method stub
		ChatMessage m = (ChatMessage) msg.getObject();
		System.out.println(""+m.getData());
		if(m.getType() == ChatMessage.REQUEST)
		{
			switch(m.getFlag())
			{
			// in case of connection request
			case ChatMessage.CONNECT : accept(m.getSource());
			break;
			// chatroom creation request
			case ChatMessage.CREA : createChatRoom(m.getData(),name);
			ChatMessage answer = new ChatMessage(address,m.getSource(),controlCluster,ChatMessage.ACK,ChatMessage.CREA, m.getData());
			driver.sendMessage(answer);
			break;
			// getting available chatrooms request
			case ChatMessage.CHATROOMS : sendChatRooms(m.getSource());
			break;
		
			}
		}
		
	}
	// accept a client on the network
	public void accept(Address Addr)
	{ 	
		System.out.println(""+Addr);
		ChatMessage msg = new ChatMessage(address, Addr, controlCluster, ChatMessage.ACK, ChatMessage.CONNECT, "connection established with ; " +Addr);
		driver.sendMessage(msg);
		System.out.println("message sent");
	}
	//create a new chatroom
	public void createChatRoom(String chatRoomName, String name)
	{
		ChatRoomController chat = new ChatRoomController(chatRoomName,name);
		chat.addObserver(this);
		chatRooms.add(chat);
		sendChatRooms(null);
	}
	//kick a client from the network

	public void kick(Address dest)
	{
		ChatMessage msg = new ChatMessage(address, dest, controlCluster, ChatMessage.ACK, ChatMessage.KICK, null);
		driver.sendMessage(msg);
	}
	// sending chatrooms available to client
	public void sendChatRooms(Address dest)
	{
		StringBuilder sb=new StringBuilder();
		int i=0;
		for(ChatRoomController crc: chatRooms)
		{
			sb.append(crc.getClusterName());
			if(i!=chatRooms.size()-1) sb.append("-");
			i++;
			
		}
		ChatMessage m = new ChatMessage(address,dest,controlCluster,ChatMessage.NOTIF,ChatMessage.CHATROOMS,sb.toString());
		driver.sendMessage(m);
	}
	public void deleteChatroom( String chatRoomName)
	{
		for(ChatRoomController c : chatRooms)
		{
			if(c.getClusterName().equalsIgnoreCase(chatRoomName)) 
			{	if(c.getAddressList().size()>1)
				for(Address user:c.getAddressList())
				{
				driver.sendMessage(new ChatMessage(address,user,controlCluster,ChatMessage.NOTIF,ChatMessage.KICK,chatRoomName));
				}
			c.delete();
			chatRooms.remove(c);
			sendChatRooms(null);
			}
		}
	}
	// À faire lorsqu'on ferme la fenêtre du serveur
public void leave()
{
	driver.sendMessage(new ChatMessage(address,null,controlCluster,ChatMessage.NOTIF,ChatMessage.LEAVE,"server shutting down"));
	
}
public void kickFromChatroom(String chatroom,String user)
{
	for(ChatRoomController c : chatRooms)
	{
		if(c.getClusterName().equalsIgnoreCase(chatroom)) 
		{
			Address a =c.getUserAddress(user);
			driver.sendMessage(new ChatMessage(address,a,controlCluster,ChatMessage.NOTIF,ChatMessage.KICK,chatroom));
		}
			
	}
	
}
	@Override
	public void onViewChanged(View v) {
		// TODO Auto-generated method stub
		
		
	}
	
	@Override
	// each time the userlist of a chatroom has been updated we tell all the clients
	public void update(Observable o, Object arg) {
		
		// TODO Auto-generated method stub
		ChatRoomController c= (ChatRoomController) o;
		List <String> list = (List <String>) arg;
		StringBuilder sb=new StringBuilder();
		sb.append(c.getClusterName());
		for(String s : list)
		{
			sb.append("-").append(s);
		}
		ChatMessage msg= new ChatMessage(address,null,controlCluster,ChatMessage.NOTIF,ChatMessage.USERS,sb.toString());
		driver.sendMessage(msg);
		
	}

}
